home *** CD-ROM | disk | FTP | other *** search
/ Utilities Professional 1-1500 / Utilities Professional 1-1500 (1994)(WPD)[!].iso / 12511500 / var1449.dms / var1449.adf / AudioDevice / Example4.c < prev    next >
C/C++ Source or Header  |  1992-04-24  |  16KB  |  542 lines

  1. /***********************************************************/
  2. /*                                                         */
  3. /* Amiga C Encyclopedia (ACE) V3.0      Amiga C Club (ACC) */
  4. /* -------------------------------      ------------------ */
  5. /*                                                         */
  6. /* Book:    ACM Devices                 Amiga C Club       */
  7. /* Chapter: AudioDevice                 Tulevagen 22       */
  8. /* File:    Example4.c                  181 41  LIDINGO    */
  9. /* Author:  Anders Bjerin               SWEDEN             */
  10. /* Date:    92-04-21                                       */
  11. /* Version: 1.00                                           */
  12. /*                                                         */
  13. /*   Copyright 1992, Anders Bjerin - Amiga C Club (ACC)    */
  14. /*                                                         */
  15. /* Registered members may use this program freely in their */
  16. /*     own commercial/noncommercial programs/articles.     */
  17. /*                                                         */
  18. /***********************************************************/
  19.  
  20. /* This program demonstrates how you can play a sound */
  21. /* continuously. While the sound is being played we   */
  22. /* slowly alter the period and volume values.         */
  23.  
  24.  
  25.  
  26. #include <exec/types.h>        /* STRPTR         */
  27. #include <exec/memory.h>       /* MEMF_CHIP      */
  28. #include <devices/audio.h>     /* Audio Device   */
  29.  
  30.  
  31.  
  32. /* The audio channels: (Sadly these constants */
  33. /* have not been defined in any header file.) */ 
  34.  
  35. /* Values: */
  36. #define LEFT0B   0
  37. #define RIGHT0B  1
  38. #define RIGHT1B  2
  39. #define LEFT1B   3
  40.  
  41. /* Bit fields: */
  42. #define LEFT0F   (1<<LEFT0B)
  43. #define RIGHT0F  (1<<RIGHT0B)
  44. #define RIGHT1F  (1<<RIGHT1B)
  45. #define LEFT1F   (1<<LEFT1B)
  46.  
  47. /* Sound priorities: */
  48. #define SOUND_UNSTOPPABLE  127
  49. #define SOUND_EMERGENCIES   95
  50. #define SOUND_ATTENTION     85
  51. #define SOUND_SPEECH        75
  52. #define SOUND_INFORMATION   60
  53. #define SOUND_MUSIC          0
  54. #define SOUND_EFFECT       -35
  55. #define SOUND_BACKGROUND   -90
  56. #define SOUND_SILENCE     -128
  57.  
  58. /* The clock constant: */
  59. #define NTSC_CLOCK    3579545 /* American Amigas - 60Hz */
  60. #define PAL_CLOCK     3546895 /* European Amigas - 50Hz */
  61.  
  62. /* Define min/max-volumes: */
  63. #define MAXVOLUME  64
  64. #define MINVOLUME   0
  65.  
  66.  
  67.  
  68. /* Declare a pointer to our reply port: */
  69. struct MsgPort *replymp = NULL;
  70.  
  71. /* Declare a pointer to our audio request block: */
  72. struct IOAudio *audio_req = NULL;
  73.  
  74. /* Declare another request block which we  */
  75. /* will use to change to volume and period */
  76. /* values with:                            */
  77. struct IOAudio *change_req = NULL;
  78.  
  79.  
  80.  
  81. /* Our list of preffered channel combinations: */
  82. /* (First we try to reserve the first channel, */
  83. /* then the second, third and finally fourth   */
  84. /* audio channel.)                             */
  85. UBYTE allocation_array[]=
  86. {
  87.   LEFT0F,
  88.   RIGHT0F,
  89.   RIGHT1F,
  90.   LEFT1F
  91. };
  92.  
  93.  
  94.  
  95. /* Declare a pointer to some soundwave data: */
  96. BYTE *engine_wave = NULL;
  97.  
  98. /* This is some sampled sound data which will be copied */
  99. /* into some chip memory before we try to play it:      */
  100.  
  101. /* (If you have the SAS (Lattice) C Copmiler you can    */
  102. /* instead use the keyword "chip" just after the word   */
  103. /* "BYTE". The data will then immediately be placed in  */
  104. /* chip memory, and you do then not need to allocate    */
  105. /* any extra memory and copy the data into it.)         */
  106.  
  107. /************************************/
  108. /* SoundData prepared by PrintSound */
  109. /* Anders Bjerin       Amiga C Club */
  110. /*                                  */
  111. /* File name:         CarEngine.snd */
  112. /* Record Rate:               28185 */
  113. /* File Length:                1000 */
  114. /************************************/
  115.  
  116. BYTE engine_data[]=
  117. {
  118.   0,0,-105,-97,-70,-41,-30,-37,-43,-37,-14,
  119.   10,24,21,3,-11,-14,-13,-16,-27,-37,-40,
  120.   -42,-52,-127,-74,-76,-72,-64,-55,-97,-38,-97,
  121.   -99,-14,0,14,37,58,117,70,64,56,50,
  122.   40,29,21,21,-11,31,-19,30,-19,27,32,
  123.   41,51,54,52,47,45,15,50,50,49,46,
  124.   41,35,32,32,33,38,41,36,29,-13,-13,
  125.   31,38,47,52,53,47,39,37,40,44,41,
  126.   26,11,0,1,0,-8,-15,-15,41,41,0,
  127.   -1,0,5,13,21,27,24,19,18,12,-5,
  128.   -28,-48,-60,-68,-73,-76,-76,-77,-79,-79,-78,
  129.   35,33,-127,-64,27,-103,-97,-104,-87,-55,-32,
  130.   -17,-17,-19,-13,0,24,47,61,69,68,123,
  131.   41,23,11,0,-6,-12,-22,-24,-17,-11,-14,
  132.   -30,-47,-56,-58,-51,-35,-22,-5,8,15,17,
  133.   16,17,21,28,31,31,32,32,28,21,12,
  134.   8,7,4,4,11,21,-19,23,14,9,12,
  135.   -9,25,29,30,35,45,49,44,33,20,18,
  136.   23,29,27,22,22,27,29,27,61,24,32,
  137.   42,59,55,46,31,21,11,1,4,1,19,
  138.   18,0,7,9,10,8,10,15,18,17,16,
  139.   17,16,9,-6,-25,-51,-63,-61,-47,21,-36,
  140.   -40,-44,-40,-32,-26,-23,-19,-18,-19,55,-11,
  141.   -11,-70,-97,-112,-117,-106,-79,-58,-54,-57,-57,
  142.   -51,-38,-8,19,31,31,22,4,-4,-10,-15,
  143.   -22,71,-41,-45,-42,-31,-22,-23,-29,-32,-27,
  144.   -17,-2,63,63,19,29,63,47,50,54,61,
  145.   63,61,58,57,57,59,57,47,-31,49,44,
  146.   43,43,41,21,37,39,33,44,31,29,31,
  147.   37,27,31,23,21,21,23,17,14,19,15,
  148.   0,5,113,13,29,4,11,20,25,16,5,
  149.   0,5,13,12,3,-12,-17,-8,4,3,-4,
  150.   -14,-18,-15,-10,-12,-19,-26,-27,-21,-16,-55,
  151.   -67,-51,-75,-77,-89,-97,-99,35,35,35,-119,
  152.   -117,-123,-115,-123,-113,-115,-105,-81,-117,-44,-45,
  153.   -49,-42,-23,-103,38,53,66,69,61,117,117,
  154.   20,123,121,18,3,-9,-15,-8,-2,-3,-10,
  155.   -27,-37,-32,-9,9,24,25,23,23,30,35,
  156.   33,24,18,18,24,32,33,28,22,23,32,
  157.   40,-11,49,50,54,117,121,107,65,51,101,
  158.   91,89,57,50,40,37,38,25,25,15,25,
  159.   2,1,23,-9,-11,-3,5,21,10,4,0,
  160.   7,27,39,32,1,-2,1,5,-1,-14,-23,
  161.   -21,-16,-16,-19,-22,-22,-23,33,-23,33,-18,
  162.   -22,33,9,-41,9,-46,-56,-62,-59,-46,-40,
  163.   -44,-52,-57,-65,-125,-123,-123,-123,-78,-55,-38,
  164.   -36,-38,-33,-21,0,25,47,57,54,37,15,
  165.   1,0,-2,-11,-32,-55,-62,-54,-41,-41,-49,
  166.   -54,-51,-44,-33,-21,-11,2,22,45,60,77,
  167.   68,121,123,123,99,99,123,123,97,29,21,
  168.   18,25,25,17,1,0,41,0,56,58,55,
  169.   55,55,44,11,49,47,39,25,12,7,9,
  170.   8,-2,-16,-19,-12,-5,-8,-14,-12,-2,5,
  171.   7,1,0,6,18,27,23,4,-14,-18,-4,
  172.   0,-2,-10,-8,3,20,33,34,26,21,28,
  173.   41,44,28,3,-11,-15,-19,-31,-49,-64,-68,
  174.   -64,-59,-58,-61,-64,-64,-66,-72,-77,-78,-79,
  175.   -78,-67,-50,-28,-11,-1,0,89,43,123,73,
  176.   121,117,113,42,28,22,16,1,-17,-29,-37,
  177.   -38,-38,67,-38,-35,-32,-30,-24,-15,-5,-1,
  178.   1,9,18,22,17,7,0,-3,3,11,14,
  179.   10,9,17,30,33,25,16,13,21,27,28,
  180.   27,29,33,11,41,35,35,32,32,33,28,
  181.   -35,7,3,4,9,10,8,6,9,18,22,
  182.   22,22,28,42,52,53,45,75,83,91,11,
  183.   6,11,25,7,-30,25,-15,-26,-37,-31,23,
  184.   6,16,11,4,23,1,0,-10,-34,-49,-52,
  185.   -23,-79,-79,-63,-89,-73,-79,-105,-127,-123,-121,
  186.   -119,-117,-115,-75,-76,-62,-54,-51,-48,-40,-15,
  187.   6,-27,42,47,50,-23,71,-21,-19,121,121,
  188.   121,40,-1,26,12,-55,0,-53,-53,-37,3,
  189.   -11,0,5,-6,-5,2,12,24,13,28,22,
  190.   21,17,34,19,23,34,35,41,54,63,64,
  191.   59,56,56,54,91,91,89,43,43,43,43,
  192.   43,87,17,8,9,33,79,17,6,35,-7,
  193.   0,9,35,-6,51,-1,12,9,1,7,35,
  194.   3,-1,7,3,-3,-4,5,20,23,14,-15,
  195.   -17,-18,-19,-25,-21,-18,-14,-12,-17,-29,33,
  196.   -32,-31,-40,-59,-69,-72,-74,-82,-97,-111,-122,
  197.   -123,-113,-77,-97,-79,-96,-83,-71,-66,-77,-86,
  198.   29,-49,-15,27,-2,-5,1,28,21,80,89,
  199.   87,105,105,49,40,30,-23,5,-4,-7,-15,
  200.   -11,-22,-63,-26,-22,-26,-33,-31,-10,8,27,
  201.   31,30,34,46,63,69,64,-1,15,19,-1,
  202.   21,21,43,39,40,45,47,44,40,40,44,
  203.   47,48,49,3,53,50,46,45,45,46,42,
  204.   13,20,14,-15,18,18,11,17,9,19,25,
  205.   28,29,115,25,41,39,34,31,30,28,21,
  206.   5,-13,29,-14,-9,-20,-38,-55,-55,-46,-31,
  207.   -24,-19,-24,-36,-49,-60,-78,-85,-78,-67,-62,
  208.   -71,-82,-87,-84,-81,-84,-119,-96,-96,27,
  209. };
  210.  
  211.  
  212. /* To sample sound you have to use a sound sampler. If */
  213. /* you do not have any I can help you and do it for    */
  214. /* you, free of charge. (Registered members only.)     */
  215.  
  216.  
  217.  
  218.  
  219. /* Declare our functions: */
  220. void main();
  221. void clean_up( STRPTR text );
  222.  
  223.  
  224.  
  225. void main()
  226. {
  227.   /* Error messages: */
  228.   BYTE error;
  229.  
  230.   /* The channel we have received: */
  231.   UBYTE channel;
  232.  
  233.   /* Used in the loops: */
  234.   int loop;
  235.  
  236.   /* Used when we copy the first request */
  237.   /* block to the second one:            */
  238.   BYTE *first_ptr;
  239.   BYTE *second_ptr;
  240.  
  241.  
  242.  
  243.  
  244.   /* Get a reply port: (No name, priority 0) */
  245.   replymp = (struct MsgPort *)
  246.     CreatePort( NULL, 0 );
  247.   if( !replymp )
  248.     clean_up( "Could not create the reply port!" );
  249.  
  250.  
  251.  
  252.   /* Allocate and preinitialize an audio request block: */
  253.   audio_req = (struct IOAudio *)
  254.     CreateExtIO( replymp, sizeof( struct IOAudio ) );
  255.   if( !audio_req )
  256.     clean_up( "Not enough memory for the first IOAudio structure!" );
  257.  
  258.  
  259.  
  260.   /* Allocate and preinitialize the other audio request block: */
  261.   change_req = (struct IOAudio *)
  262.     CreateExtIO( replymp, sizeof( struct IOAudio ) );
  263.   if( !change_req )
  264.     clean_up( "Not enough memory for the second IOAudio structure!" );
  265.  
  266.  
  267.  
  268.   /* Open the Audio Device: (We will try to */
  269.   /* reserve a sound channel later on.)     */
  270.   error = OpenDevice( AUDIONAME, 0, audio_req, 0 );
  271.   if( error )
  272.   {
  273.     /* Clear the "io_Device" flag since we have not opened the device: */
  274.     audio_req->ioa_Request.io_Device = NULL;
  275.   
  276.     /* Quit: */
  277.     clean_up( "Could not open the Audio Device!" );
  278.   }
  279.   
  280.  
  281.  
  282.   /* Try to reserve a channel: */
  283.   audio_req->ioa_Request.io_Command = ADCMD_ALLOCATE;
  284.  
  285.   /* Set sound priority: (We are going to play a sound effect.) */
  286.   audio_req->ioa_Request.io_Message.mn_Node.ln_Pri = SOUND_EFFECT;
  287.  
  288.   /* Do not wait for any channels to be free, */
  289.   /* return immediately, successfully or not: */
  290.   audio_req->ioa_Request.io_Flags = ADIOF_NOWAIT;
  291.  
  292.   /* Give the request block a pointer to our allocation array: */
  293.   audio_req->ioa_Data = allocation_array;
  294.   
  295.   /* Set the length of the allocation array: */
  296.   audio_req->ioa_Length = sizeof( allocation_array );
  297.          
  298.   /* Do our request: */
  299.   BeginIO( audio_req );
  300.  
  301.   /* Wait for the request to be completed: */
  302.   error = WaitIO( audio_req );
  303.  
  304.   /* Everything OK? */
  305.   if( error )
  306.     clean_up( "No channel available!" );
  307.  
  308.  
  309.  
  310.   /* Check which channel we received: */
  311.   channel = (UBYTE) audio_req->ioa_Request.io_Unit;
  312.  
  313.   /* Check which channel we received: */
  314.   channel = (UBYTE) audio_req->ioa_Request.io_Unit;
  315.  
  316.   if( channel & LEFT0F )
  317.     printf( "First left channel!\n" );
  318.  
  319.   if( channel & RIGHT0F )
  320.     printf( "First right channel!\n" );
  321.  
  322.   if( channel & RIGHT1F )
  323.     printf( "Second right channel!\n" );
  324.  
  325.   if( channel & LEFT1F )
  326.     printf( "Second left channel!\n" );
  327.  
  328.  
  329.  
  330.   /* Allocate some memory where we can store the waveform we   */
  331.   /* want to use. Note that it must be Chip memory, and placed */
  332.   /* on a word boundary!                                       */
  333.   engine_wave = (BYTE *) AllocMem( sizeof( engine_data ), MEMF_CHIP );
  334.   if( !engine_wave )
  335.     clean_up( "Could not allocate enough memory for the engine wave!" );  
  336.  
  337.   /* Copy the engine data to some chip memory: */
  338.   for( loop = 0; loop < sizeof( engine_data ); loop++ )
  339.     engine_wave[ loop ] = engine_data[ loop ];
  340.  
  341.  
  342.   
  343.   /* Give the request block a pointer to the waveform: */
  344.   audio_req->ioa_Data = engine_wave;
  345.  
  346.   /* Set the length of the waveform:    */
  347.   /* (Must be an even number of bytes.) */
  348.   audio_req->ioa_Length = sizeof( engine_data );
  349.  
  350.   /* Play forever: (The only whay to stop it is to send a */
  351.   /* ADCMD_FINISH command, or call AbortIO().)            */
  352.   audio_req->ioa_Cycles = 0;
  353.  
  354.   /* Going to play a tune: */
  355.   audio_req->ioa_Request.io_Command = CMD_WRITE;
  356.  
  357.   /* Use the volume and period fields of the request block: */
  358.   /* (If we do not set this flag the previous volume and    */
  359.   /* period values will be used.)                           */
  360.   audio_req->ioa_Request.io_Flags = ADIOF_PERVOL;
  361.  
  362.   /* Medium volume: */
  363.   audio_req->ioa_Volume = 32;
  364.  
  365.   /* Set the period: (The period value can be calculated  */
  366.   /* by dividing the clock constant with the record rate. */
  367.   /* The record rate is also printed by PrintSound,       */
  368.   /* together with the sample data values.)               */
  369.   audio_req->ioa_Period = PAL_CLOCK / 28185;
  370.  
  371.  
  372.  
  373.   /* Copy the first request block to the secon one: (byte by byte) */
  374.  
  375.   /* Get the start addresses of both request blocks: */
  376.   first_ptr = (BYTE *) audio_req;
  377.   second_ptr = (BYTE *) change_req;
  378.  
  379.   /* Copy byte by byte: */
  380.   for( loop = 0; loop < sizeof( struct IOAudio ); loop++ )
  381.   {
  382.     /* Copy: */
  383.     *second_ptr = *first_ptr;
  384.     
  385.     /* Next byte: */
  386.     first_ptr++;
  387.     second_ptr++;
  388.   }
  389.  
  390.  
  391.  
  392.   /* Tell the user to be prepared: */
  393.   printf( "This can not be a VOLVO!\n" );
  394.  
  395.   /* Start to play the sound: */
  396.   BeginIO( audio_req );
  397.   
  398.  
  399.  
  400.   /* In this very long loop we will 10 times change the */
  401.   /* volume and period values:                          */
  402.   for( loop=0; loop < 100000; loop++ )
  403.   {
  404.     /* 10 times should the sound be altered: */
  405.     if( !(loop % 10000) )
  406.     {
  407.       /* We are going to alter the volume and period values */
  408.       /* on one of the sound channels:                      */
  409.       change_req->ioa_Request.io_Command = ADCMD_PERVOL;
  410.  
  411.       /* The change should first occur when we the sound */
  412.       /* has reached the end of the cycle. If you do not */
  413.       /* set this flag in this example I do not think    */
  414.       /* anyone would hear any disturbing clicks while   */
  415.       /* the volume and period are changed, but if you   */
  416.       /* play very clean sounds it might be necessary.   */
  417.       change_req->ioa_Request.io_Flags = ADIOF_SYNCCYCLE;
  418.  
  419.       /* Slowly increase the volume: */
  420.       change_req->ioa_Volume += 2;
  421.  
  422.       /* Also increase the period value: */
  423.       change_req->ioa_Period += 20;
  424.  
  425.  
  426.  
  427.       /* Set a mark: */
  428.       printf( "*" );
  429.     
  430.  
  431.  
  432.       /* Make the change: */
  433.       BeginIO( change_req );
  434.  
  435.       /* Wait for the change to be completed: */
  436.       error = WaitIO( change_req );
  437.  
  438.       /* Could we successfully alter the sound? */
  439.       if( error )
  440.       {
  441.         /* We could not alter the sound, some one */
  442.         /* has stolen our channel!!!              */
  443.  
  444.         /* Quit: */        
  445.         clean_up( "Could not alter the sound!" );
  446.       }
  447.     }
  448.   }
  449.  
  450.  
  451.  
  452.   /* Stop the sound: */
  453.   change_req->ioa_Request.io_Command = ADCMD_FINISH;
  454.  
  455.   /* But first wait for the cycle to be completed: */
  456.   change_req->ioa_Request.io_Flags = ADIOF_SYNCCYCLE;
  457.  
  458.   /* Send the command: */
  459.   BeginIO( change_req );
  460.  
  461.   /* Wait for the sound to be stopped: (This command can */
  462.   /* not fail so we do not have to check for any error   */
  463.   /* messages.)                                          */
  464.   WaitIO( change_req );
  465.  
  466.  
  467.   /* An easier way to stop a sound is simlply to call the    */
  468.   /* AbortIO() function directly, and not bother about       */
  469.   /* using a separate request. You can choose either method, */
  470.   /* it will make no difference, although some programmers   */
  471.   /* tend to prefer the ADCMD_FINISH command.                */
  472.   /*                                                         */
  473.   /* AbortIO( audio_req );                                   */
  474.  
  475.  
  476.  
  477.   /* Clean up and quit: */
  478.   clean_up( "The End!" );
  479. }
  480.  
  481.  
  482.  
  483. /* Close and return everything that has been */
  484. /* opened and allocated before we quit:      */
  485.  
  486. void clean_up( STRPTR text )
  487. {
  488.   /* New line: */
  489.   printf( "\n" );
  490.   
  491.   /* If we have a request block and it does not contain   */
  492.   /* any errors we know that a channel has been allocated */
  493.   /* and must be deallocated:                             */
  494.   if( audio_req && !(audio_req->ioa_Request.io_Error) )
  495.   {
  496.     /* Free the channel: */
  497.     audio_req->ioa_Request.io_Command = ADCMD_FREE;
  498.  
  499.     /* We are allowed to use the function DoIO() for */
  500.     /* this request since it will not change any     */
  501.     /* values that are vital for us:                 */ 
  502.     DoIO( audio_req );
  503.     
  504.     /* The lock is automatically unlocked when we */
  505.     /* free the audio channel.                    */
  506.   }
  507.  
  508.   /* Empty the reply port: */
  509.   while( GetMsg( replymp ) )
  510.     printf( "Collected a message at the reply port.\n" );
  511.   
  512.   /* If we have a request block and the "io_Device" field  */
  513.   /* is not zero, we know that the device has successfully */
  514.   /* been opened and must now be closed:                   */ 
  515.   if( audio_req && audio_req->ioa_Request.io_Device )
  516.     CloseDevice( audio_req );
  517.  
  518.   /* Remove the replyport: */
  519.   if( replymp )
  520.     DeletePort( replymp);
  521.  
  522.   /* Dealocate the first IOAudio structure: */
  523.   if( audio_req )
  524.     DeleteExtIO( audio_req, sizeof( struct IOAudio ) );
  525.  
  526.   /* Dealocate the second IOAudio structure: */
  527.   if( change_req )
  528.     DeleteExtIO( change_req, sizeof( struct IOAudio ) );
  529.  
  530.   /* Dealocate the engine waveform: */
  531.   if( engine_wave )
  532.     FreeMem( engine_wave, sizeof( engine_data ) );
  533.  
  534.   /* Print the last message: */
  535.   printf( "%s\n", text );
  536.  
  537.   /* Quit: */
  538.   exit( 0 );
  539. }
  540.  
  541.  
  542.